0384. 打乱数组【中等】
1. 📝 题目描述
给你一个整数数组 nums,设计算法来打乱一个没有重复元素的数组。打乱后,数组的所有排列应该是 等可能 的。
实现 Solution class:
Solution(int[] nums)使用整数数组nums初始化对象int[] reset()重设数组到它的初始状态并返回int[] shuffle()返回数组随机打乱后的结果
示例 1:
txt
输入
["Solution", "shuffle", "reset", "shuffle"]
[[[1, 2, 3]], [], [], []]
输出
[null, [3, 1, 2], [1, 2, 3], [1, 3, 2]]
解释
Solution solution = new Solution([1, 2, 3]);
solution.shuffle(); // 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。例如,返回 [3, 1, 2]
solution.reset(); // 重设数组到它的初始状态 [1, 2, 3]。返回 [1, 2, 3]
solution.shuffle(); // 随机返回数组 [1, 2, 3] 打乱后的结果。例如,返回 [1, 3, 2]1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
提示:
1 <= nums.length <= 50-10^6 <= nums[i] <= 10^6nums中的所有元素都是 唯一的- 最多可以调用
10^4次reset和shuffle
2. 🎯 s.1 - Fisher-Yates 洗牌
c
typedef struct {
int* original;
int* nums;
int size;
} Solution;
Solution* solutionCreate(int* nums, int numsSize) {
Solution* obj = (Solution*)malloc(sizeof(Solution));
obj->original = (int*)malloc(sizeof(int) * numsSize);
obj->nums = (int*)malloc(sizeof(int) * numsSize);
memcpy(obj->original, nums, sizeof(int) * numsSize);
memcpy(obj->nums, nums, sizeof(int) * numsSize);
obj->size = numsSize;
return obj;
}
int* solutionReset(Solution* obj, int* retSize) {
memcpy(obj->nums, obj->original, sizeof(int) * obj->size);
*retSize = obj->size;
return obj->nums;
}
int* solutionShuffle(Solution* obj, int* retSize) {
for (int i = obj->size - 1; i > 0; i--) {
int j = rand() % (i + 1);
int tmp = obj->nums[i]; obj->nums[i] = obj->nums[j]; obj->nums[j] = tmp;
}
*retSize = obj->size;
return obj->nums;
}
void solutionFree(Solution* obj) {
free(obj->original); free(obj->nums); free(obj);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
js
/**
* @param {number[]} nums
*/
var Solution = function (nums) {
this.original = [...nums]
this.nums = nums
}
/**
* @return {number[]}
*/
Solution.prototype.reset = function () {
this.nums = [...this.original]
return this.nums
}
/**
* @return {number[]}
*/
Solution.prototype.shuffle = function () {
for (let i = this.nums.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
;[this.nums[i], this.nums[j]] = [this.nums[j], this.nums[i]]
}
return this.nums
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
py
class Solution:
def __init__(self, nums: List[int]):
self.original = nums[:]
self.nums = nums
def reset(self) -> List[int]:
self.nums = self.original[:]
return self.nums
def shuffle(self) -> List[int]:
for i in range(len(self.nums) - 1, 0, -1):
j = random.randint(0, i)
self.nums[i], self.nums[j] = self.nums[j], self.nums[i]
return self.nums1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
- 时间复杂度:
shuffle ,reset - 空间复杂度:
,存储原始数组副本
算法思路:
- Fisher-Yates 洗牌:从后往前,第
个位置随机与 中某个位置交换 - 保证每种排列出现的概率均等